/*
 * USB测试程序主入口
 * 功能：Linux下USB主机模式和设备模式的读写测试
 * 支持：USB Host读写、USB Device模拟、libusb接口测试
 * 作者：test_code项目
 * 平台：Linux嵌入式系统
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <signal.h>
#include <errno.h>
#include "usb_utils.h"

static volatile int running = 1;

void signal_handler(int sig) {
    if (sig == SIGINT || sig == SIGTERM) {
        printf("\n接收到退出信号，正在停止USB测试...\n");
        running = 0;
    }
}

void print_usage(const char *program_name) {
    printf("用法: %s [选项]\n", program_name);
    printf("Linux USB读写测试程序\n\n");
    printf("选项:\n");
    printf("  -m, --mode=MODE       测试模式:\n");
    printf("                        host     - USB主机模式测试\n");
    printf("                        device   - USB设备模式测试\n");
    printf("                        gadget   - USB Gadget测试\n");
    printf("                        scan     - 扫描USB设备\n");
    printf("  -v, --vendor=VID      USB厂商ID (十六进制)\n");
    printf("  -p, --product=PID     USB产品ID (十六进制)\n");
    printf("  -d, --device=PATH     设备路径 (如 /dev/ttyUSB0)\n");
    printf("  -t, --test=TYPE       测试类型:\n");
    printf("                        read     - 读取测试\n");
    printf("                        write    - 写入测试\n");
    printf("                        loop     - 回环测试\n");
    printf("                        speed    - 速度测试\n");
    printf("  -s, --size=BYTES      数据大小 (字节)\n");
    printf("  -c, --count=NUM       测试次数\n");
    printf("  -i, --info            显示USB系统信息\n");
    printf("  -h, --help            显示帮助信息\n");
    printf("\n示例:\n");
    printf("  %s -i                           # 显示USB系统信息\n", program_name);
    printf("  %s -m scan                      # 扫描所有USB设备\n", program_name);
    printf("  %s -m host -v 0x1234 -p 0x5678  # 测试指定USB设备\n", program_name);
    printf("  %s -m device -d /dev/ttyUSB0    # 测试USB串口设备\n", program_name);
    printf("  %s -m gadget -t loop            # USB Gadget回环测试\n", program_name);
}

int run_host_test(uint16_t vendor_id, uint16_t product_id, const char *test_type, 
                  size_t data_size, int test_count) {
    printf("=== USB主机模式测试 ===\n");
    printf("厂商ID: 0x%04X\n", vendor_id);
    printf("产品ID: 0x%04X\n", product_id);
    printf("测试类型: %s\n", test_type);
    printf("数据大小: %zu 字节\n", data_size);
    printf("测试次数: %d\n", test_count);
    
    // 初始化libusb
    if (usb_host_init() != 0) {
        printf("USB主机初始化失败\n");
        return -1;
    }
    
    // 查找并打开USB设备
    usb_device_handle_t *device = usb_host_open_device(vendor_id, product_id);
    if (!device) {
        printf("无法找到或打开USB设备 (VID:0x%04X PID:0x%04X)\n", vendor_id, product_id);
        usb_host_cleanup();
        return -1;
    }
    
    printf("USB设备打开成功\n");
    
    // 显示设备信息
    usb_device_info_t info;
    if (usb_host_get_device_info(device, &info) == 0) {
        usb_print_device_info(&info);
    }
    
    int result = 0;
    
    // 执行测试
    if (strcmp(test_type, "read") == 0) {
        result = usb_host_read_test(device, data_size, test_count);
    } else if (strcmp(test_type, "write") == 0) {
        result = usb_host_write_test(device, data_size, test_count);
    } else if (strcmp(test_type, "loop") == 0) {
        result = usb_host_loopback_test(device, data_size, test_count);
    } else if (strcmp(test_type, "speed") == 0) {
        result = usb_host_speed_test(device, data_size, test_count);
    } else {
        printf("未知的测试类型: %s\n", test_type);
        result = -1;
    }
    
    // 清理资源
    usb_host_close_device(device);
    usb_host_cleanup();
    
    return result;
}

int run_device_test(const char *device_path, const char *test_type, 
                    size_t data_size, int test_count) {
    printf("=== USB设备模式测试 ===\n");
    printf("设备路径: %s\n", device_path);
    printf("测试类型: %s\n", test_type);
    printf("数据大小: %zu 字节\n", data_size);
    printf("测试次数: %d\n", test_count);
    
    // 打开USB设备文件
    usb_serial_handle_t *serial = usb_serial_open(device_path);
    if (!serial) {
        printf("无法打开USB设备文件: %s\n", device_path);
        return -1;
    }
    
    printf("USB设备文件打开成功\n");
    
    int result = 0;
    
    // 执行测试
    if (strcmp(test_type, "read") == 0) {
        result = usb_serial_read_test(serial, data_size, test_count);
    } else if (strcmp(test_type, "write") == 0) {
        result = usb_serial_write_test(serial, data_size, test_count);
    } else if (strcmp(test_type, "loop") == 0) {
        result = usb_serial_loopback_test(serial, data_size, test_count);
    } else if (strcmp(test_type, "speed") == 0) {
        result = usb_serial_speed_test(serial, data_size, test_count);
    } else {
        printf("未知的测试类型: %s\n", test_type);
        result = -1;
    }
    
    // 清理资源
    usb_serial_close(serial);
    
    return result;
}

int run_gadget_test(const char *test_type, size_t data_size, int test_count) {
    printf("=== USB Gadget测试 ===\n");
    printf("测试类型: %s\n", test_type);
    printf("数据大小: %zu 字节\n", data_size);
    printf("测试次数: %d\n", test_count);
    
    // 初始化USB Gadget
    if (usb_gadget_init() != 0) {
        printf("USB Gadget初始化失败\n");
        return -1;
    }
    
    printf("USB Gadget初始化成功\n");
    
    int result = 0;
    
    // 执行测试
    if (strcmp(test_type, "read") == 0) {
        result = usb_gadget_read_test(data_size, test_count);
    } else if (strcmp(test_type, "write") == 0) {
        result = usb_gadget_write_test(data_size, test_count);
    } else if (strcmp(test_type, "loop") == 0) {
        result = usb_gadget_loopback_test(data_size, test_count);
    } else {
        printf("未知的测试类型: %s\n", test_type);
        result = -1;
    }
    
    // 清理资源
    usb_gadget_cleanup();
    
    return result;
}

int scan_usb_devices(void) {
    printf("=== 扫描USB设备 ===\n");
    
    // 初始化libusb
    if (usb_host_init() != 0) {
        printf("USB主机初始化失败\n");
        return -1;
    }
    
    // 扫描所有USB设备
    int device_count = usb_scan_all_devices();
    printf("发现 %d 个USB设备\n", device_count);
    
    // 扫描USB串口设备
    printf("\n=== USB串口设备 ===\n");
    usb_scan_serial_devices();
    
    // 扫描USB存储设备
    printf("\n=== USB存储设备 ===\n");
    usb_scan_storage_devices();
    
    // 清理资源
    usb_host_cleanup();
    
    return 0;
}

int main(int argc, char *argv[]) {
    char mode[32] = "host";
    char test_type[32] = "read";
    char device_path[256] = "";
    uint16_t vendor_id = 0x0000;
    uint16_t product_id = 0x0000;
    size_t data_size = 1024;
    int test_count = 10;
    int show_info = 0;
    
    // 长选项定义
    static struct option long_options[] = {
        {"mode",     required_argument, 0, 'm'},
        {"vendor",   required_argument, 0, 'v'},
        {"product",  required_argument, 0, 'p'},
        {"device",   required_argument, 0, 'd'},
        {"test",     required_argument, 0, 't'},
        {"size",     required_argument, 0, 's'},
        {"count",    required_argument, 0, 'c'},
        {"info",     no_argument,       0, 'i'},
        {"help",     no_argument,       0, 'h'},
        {0, 0, 0, 0}
    };
    
    // 解析命令行参数
    int opt;
    int option_index = 0;
    while ((opt = getopt_long(argc, argv, "m:v:p:d:t:s:c:ih", long_options, &option_index)) != -1) {
        switch (opt) {
            case 'm':
                strncpy(mode, optarg, sizeof(mode) - 1);
                mode[sizeof(mode) - 1] = '\0';
                break;
            case 'v':
                vendor_id = (uint16_t)strtoul(optarg, NULL, 16);
                break;
            case 'p':
                product_id = (uint16_t)strtoul(optarg, NULL, 16);
                break;
            case 'd':
                strncpy(device_path, optarg, sizeof(device_path) - 1);
                device_path[sizeof(device_path) - 1] = '\0';
                break;
            case 't':
                strncpy(test_type, optarg, sizeof(test_type) - 1);
                test_type[sizeof(test_type) - 1] = '\0';
                break;
            case 's':
                data_size = strtoul(optarg, NULL, 10);
                break;
            case 'c':
                test_count = atoi(optarg);
                break;
            case 'i':
                show_info = 1;
                break;
            case 'h':
                print_usage(argv[0]);
                return 0;
            default:
                print_usage(argv[0]);
                return 1;
        }
    }
    
    // 注册信号处理器
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    
    printf("USB测试程序启动\n");
    printf("========================\n");
    
    // 显示系统信息
    if (show_info) {
        usb_show_system_info();
        return 0;
    }
    
    // 参数有效性检查
    if (data_size == 0 || test_count <= 0) {
        printf("错误：数据大小和测试次数必须大于0\n");
        return 1;
    }
    
    // 执行对应的测试模式
    int result = 0;
    if (strcmp(mode, "scan") == 0) {
        result = scan_usb_devices();
    } else if (strcmp(mode, "host") == 0) {
        if (vendor_id == 0 && product_id == 0) {
            printf("警告：未指定厂商ID和产品ID，将尝试查找第一个可用设备\n");
        }
        result = run_host_test(vendor_id, product_id, test_type, data_size, test_count);
    } else if (strcmp(mode, "device") == 0) {
        if (strlen(device_path) == 0) {
            printf("错误：设备模式需要指定设备路径\n");
            return 1;
        }
        result = run_device_test(device_path, test_type, data_size, test_count);
    } else if (strcmp(mode, "gadget") == 0) {
        result = run_gadget_test(test_type, data_size, test_count);
    } else {
        printf("错误：未知的测试模式 '%s'\n", mode);
        printf("支持的模式: host, device, gadget, scan\n");
        return 1;
    }
    
    if (result == 0) {
        printf("\nUSB测试完成\n");
    } else {
        printf("\nUSB测试失败\n");
    }
    
    return result;
}